import { OrderService, Shipment, ShipmentItem } from "@mallfoundry/order"
import { Address, CarrierCode, Track, TrackingService, TrackingStatus } from "@mallfoundry/shipping"
import { Button, Card, Col, Descriptions, Form, Input, Modal, Radio, Row, Select, Table, Tabs, Timeline, Typography } from "antd"
import { ColumnProps } from "antd/es/table"
import { TableRowSelection } from "antd/es/table/interface"
import * as _ from "lodash"
import * as React from "react"
import { useEffect, useState } from "react"
import { useCarrier, useCarriers } from "../shipping/carrier"
import { OrderTableItem } from "./order-item"
import classes from "./order-shipments.module.scss"

const { Text } = Typography
const { TabPane } = Tabs

interface ShipmentTrackingProps {
  shippingProvider: string
  trackingNumber: string
}

function ShipmentTracking(props: ShipmentTrackingProps) {
  const { shippingProvider, trackingNumber } = props
  const [track, setTrack] = useState(new Track())
  const { Unknown, InTransit, Delivered } = TrackingStatus
  useEffect(() => {
    if (_.isUndefined(trackingNumber) || _.isNull(trackingNumber)) {
      return
    }
    TrackingService
      .getTrack(shippingProvider as CarrierCode, trackingNumber)
      .then(setTrack)
  }, [shippingProvider, trackingNumber])


  function renderTrackingStatus(status?: TrackingStatus): string {
    if (status === Delivered) {
      return "已签收"
    } else if (status === InTransit) {
      return "运输中"
    }
    return "无物流信息"
  }

  return (<>
    <Descriptions column={1}>
      <Descriptions.Item label="物流状态">
        <Text type="danger">{renderTrackingStatus(track.trackingStatus)}</Text>
      </Descriptions.Item>
    </Descriptions>
    {
      track.trackingStatus !== Unknown &&
      <Timeline className={classes.trackingTimeline}>
        {
          _.map(track.events, (event, index: number) =>
            <Timeline.Item
              key={`${event.occurredTime} ${event.message}`}
              color={index === 0 ? "red" : "gray"}>
              {event.occurredTime}<br/>{event.message}
            </Timeline.Item>)
        }
      </Timeline>
    }
  </>)
}

interface ShipmentItemDetailProps {
  item: ShipmentItem
}

function ShipmentItemDetail(props: ShipmentItemDetailProps) {
  const { item } = props
  return <div className={classes.shipmentItem}>
    <img src={item.imageUrl} alt={item.name}/>
    <Text ellipsis>{item.name}</Text>
    <Text>数量 : {item.quantity}</Text>
  </div>
}

interface ShipmentDetailProps {
  shipment: Shipment
}

function ShipmentDetail(props: ShipmentDetailProps) {
  const { shipment } = props
  const {
    consignor,
    shippingMethod,
    shippedTime,
    shippingProvider = "",
    trackingNumber = "",
    items,
  } = shipment

  const [carrier] = useCarrier(shippingProvider)

  return (
    <Card size="small">
      <Row>
        <Col span={8}>
          <Descriptions column={1}>
            <Descriptions.Item label="发货方式" children={shippingMethod}/>
            <Descriptions.Item label="发货人" children={consignor}/>
            <Descriptions.Item label="发货时间" children={shippedTime}/>
            {trackingNumber && <Descriptions.Item label="运单号" children={`${carrier?.name} ${trackingNumber}`}/>}
          </Descriptions>
          {
            _.map(items, item => <ShipmentItemDetail key={item.id} item={item}/>)
          }
        </Col>
        <Col span={16}>
          <ShipmentTracking
            shippingProvider={shippingProvider}
            trackingNumber={trackingNumber}/>
        </Col>
      </Row>
    </Card>
  )
}

interface ShipmentsProps {
  shipments?: Shipment[]
}

export default function OrderShipments(props: ShipmentsProps) {
  const { shipments } = props
  return <>
    {!_.isEmpty(shipments) &&
    <Row gutter={[24, 24]} className={classes.orderShipments}>
      <Col span={24}>
        <Tabs type="card">
          {
            _.map(shipments, (shipment, index) => (
              <TabPane tab={`包裹${index + 1}`}
                       key={`${shipment.id}${shipment.shippingProvider}${shipment.trackingNumber}`}>
                <ShipmentDetail shipment={shipment}/>
              </TabPane>
            ))
          }
        </Tabs>
      </Col>
    </Row>}
  </>
}

interface AddOrderShippingModalProps {
  orderId: string
  shippingAddress?: Address
  items: OrderTableItem[]
  visible?: boolean
  onCancel?: () => void
  onShipped?: () => void
}

export function AddOrderShippingModal(props: AddOrderShippingModalProps) {
  const { orderId, shippingAddress, items, visible, onCancel, onShipped } = props
  const [loading, setLoading] = useState(false)
  const [selectedItems, setSelectedItems] = useState([] as OrderTableItem[])
  const [carriers] = useCarriers()
  const [shippingMethod, setShippingMethod] = useState("manual")
  const shippedQuantities = _.chain(items).filter(item => item.shippingStatus).size().value()
  const unshippedQuantities = _.size(items) - shippedQuantities

  const rowSelection: TableRowSelection<OrderTableItem> = {
    type: "checkbox",
    selectedRowKeys: _.map(selectedItems, item => item.id),
    getCheckboxProps: record => ({
      disabled: record.shippingStatus,
    }),
    onSelectAll: (record, selectedRows: any[]) => {
      setSelectedItems(selectedRows)
    },
    onSelect: (record, selected, selectedRows: any[]) => {
      setSelectedItems(selectedRows)
    },
  }

  const columns: ColumnProps<OrderTableItem>[] = [
    {
      key: "name",
      dataIndex: "name",
      title: "商品",
      ellipsis: true,
    },
    {
      key: "quantity",
      dataIndex: "quantity",
      title: "数量",
      align: "center",
      width: "100px",
    },
    {
      key: "shippingStatus",
      dataIndex: "shippingStatus",
      title: "状态",
      align: "center",
      width: "100px",
      render: (status) => {
        return status ? "已发货" : "未发货"
      },
    },
    {
      key: "trackingNumber",
      dataIndex: "trackingNumber",
      title: "运单号",
      render: (trackingNumber) => {
        return _.isEmpty(trackingNumber) ? "-" : trackingNumber
      },
    },
  ]

  const formItemLayout = {
    labelCol: { span: 3 },
    wrapperCol: { span: 12 },
  }

  const tailLayout = {
    labelCol: { span: 3 },
    wrapperCol: { span: 21 },
  }

  const [form] = Form.useForm()

  function handleShipping() {
    const values = form.getFieldsValue()
    const request = _.assign(new Shipment(), {
      items: _.map(selectedItems, item => _.assign(new ShipmentItem(), {
        itemId: item.id,
        quantity: item.quantity,
      })),
    }, values, {
      shippingMethod: "快递",
    })
    setLoading(true)
    OrderService.addOrderShipment(orderId, request)
      .then(() => {
        setSelectedItems([])
        if (_.isFunction(onShipped)) {
          onShipped()
        }
      })
      .finally(() => setLoading(false))
  }

  return <Modal className={classes.addOrderShippingModal}
                width={700} title="订单发货"
                visible={visible}
                onCancel={onCancel}
                keyboard={!loading}
                maskClosable={!loading}
                closable={!loading}
                footer={<Button type="primary"
                                loading={loading}
                                onClick={handleShipping}>发货</Button>}>
    <div className={classes.shippingQuantities}>
      <span style={{ color: "#000" }}>选择商品</span> 待发货 {unshippedQuantities} 已发货 {shippedQuantities}
    </div>
    <Table rowKey="id"
           rowSelection={rowSelection}
           columns={columns}
           dataSource={items}
           pagination={false}/>
    <Form form={form} {...formItemLayout} >
      <Form.Item label="配送信息"
                 colon={false}
                 labelAlign="left"
                 {...tailLayout}
                 style={{ marginTop: "16px" }}>
        <Form.Item label="配送方式" labelAlign="right"
                   style={{ marginBottom: 0 }}
                   {...formItemLayout} children="快递"/>
        <Form.Item label="收货人" labelAlign="right" style={{ marginBottom: 0 }} {...formItemLayout} >
          <span
            className="ant-form-text">{shippingAddress?.lastName}{shippingAddress?.firstName} {shippingAddress?.phone}</span>
        </Form.Item>
        <Form.Item label="收货地址" labelAlign="right" style={{ marginBottom: 0 }} {...formItemLayout} >
          <span
            className="ant-form-text">{shippingAddress?.province}{shippingAddress?.city}{shippingAddress?.county} {shippingAddress?.address}</span>
        </Form.Item>
      </Form.Item>
      <Form.Item label="发货方式"
                 colon={false}
                 labelAlign="left"
                 style={{ marginBottom: 0 }}
                 {...tailLayout}>
        <Form.Item>
          <Radio.Group value={shippingMethod} onChange={e => setShippingMethod(e.target.value)}>
            <Radio value="manual">自己联系快递</Radio>
            <Radio value="not_need">无需物流</Radio>
          </Radio.Group>
        </Form.Item>
        {shippingMethod === "manual" && <>
          <Form.Item label="物流公司"
                     labelAlign="right"
                     name="shippingProvider"
                     {...formItemLayout}>
            <Select placeholder="请选择一个快递公司">
              {_.map(carriers, carrier =>
                <Select.Option key={carrier.code}
                               value={carrier.code as string}
                               children={carrier.name}/>)}
            </Select>
          </Form.Item>
          <Form.Item label="快递单号"
                     labelAlign="right"
                     name="trackingNumber"
                     {...formItemLayout}>
            <Input/>
          </Form.Item>
        </>}
      </Form.Item>
    </Form>
  </Modal>
}

interface EditOrderShippingModalProps {
  orderId: string
  shipments?: Shipment[]
  visible?: boolean
  onCancel?: () => void
  onSaved?: () => void
}

export function EditOrderShippingModal(props: EditOrderShippingModalProps) {
  const { orderId, shipments = [], visible, onCancel, onSaved } = props
  const [loading, setLoading] = useState(false)
  const [carriers] = useCarriers()

  function ShipmentForm({ shipment }: { shipment: Shipment }) {
    const notShipping = _.isEmpty(shipment.trackingNumber)
    return (<>
      <Form.Item label="发货方式">
        <Radio.Group value={notShipping ? 2 : 1} disabled>
          <Radio value={1}>需要物流</Radio>
          <Radio value={2}>无需物流</Radio>
        </Radio.Group>
      </Form.Item>
      {!notShipping && <div style={{ display: "flex" }}>
        <Form.Item
          label="物流公司"
          name={`${shipment.id}.shippingProvider`}
          style={{ marginRight: "16px" }}>
          <Select>
            {_.map(carriers, carrier =>
              <Select.Option key={carrier.code}
                             value={carrier.code as string}
                             children={carrier.name}/>)}
          </Select>
        </Form.Item>
        <Form.Item label="运单编号"
                   name={`${shipment.id}.trackingNumber`}
                   rules={[{ required: true }]}>
          <Input/>
        </Form.Item>
      </div>}
    </>)
  }

  const [form] = Form.useForm()

  function onOk() {
    setLoading(true)
    form.validateFields()
      .then(values =>
        _.reduce(shipments, (newShipments: Shipment[], oldShipment) => {
          const newShipment = new Shipment()
          newShipment.id = oldShipment.id
          let changed = false
          if (oldShipment.trackingNumber !== values[`${oldShipment.id}.trackingNumber`]) {
            newShipment.trackingNumber = values[`${oldShipment.id}.trackingNumber`]
            changed = true
          }

          if (oldShipment.shippingProvider !== values[`${oldShipment.id}.shippingProvider`]) {
            newShipment.shippingProvider = values[`${oldShipment.id}.shippingProvider`]
            changed = true
          }

          return changed ? [...newShipments, newShipment] : newShipments
        }, []))
      .then(requests => OrderService.updateOrderShipments(orderId, requests))
      .then(onSaved)
      .finally(() => setLoading(false))
  }

  function formValues() {
    return _.reduce(shipments, (formValues, shipment) => ({
      ...formValues,
      [`${shipment.id}.shippingProvider`]: shipment.shippingProvider,
      [`${shipment.id}.trackingNumber`]: shipment.trackingNumber,
    }), {})
  }

  return <Modal className={classes.editOrderShippingModal}
                width={700}
                title="修改物流"
                keyboard={!loading}
                maskClosable={!loading}
                closable={!loading}
                visible={visible}
                confirmLoading={loading}
                onCancel={onCancel}
                onOk={onOk}>
    <Form form={form} initialValues={formValues()}>
      {
        _.map(shipments, shipment => <ShipmentForm key={shipment.id} shipment={shipment}/>)
      }
    </Form>
  </Modal>
}
